#include "Blocks/StairsBlock.h"
#include "Components/ComponentMiner.h"
#include "Components/ComponentCreature.h"
#include "Components/ComponentCreatureModel.h"

namespace PocketSurvival
{
    StairsBlock::StairsBlock()
	{
		addInheritance(this);
		addInheritance((IPaintableBlock*)this);
	}
    
    void StairsBlock::getCreativeValues(std::vector<int32_t> &blockVec)
    {
        blockVec.push_back(Terrain::MakeBlockValue(getIndex(), 0, SetColor(0, -1)));
        for(int32_t index = 0; index < 16; ++index)
        {
            blockVec.push_back(Terrain::MakeBlockValue(getIndex(), 0, SetColor(0, index)));
        }
    }
    void StairsBlock::getDropValues(int32_t oldValue, int32_t newValue, int32_t toolLevel, std::vector<BlockDropValue> &dropValues)
    {
		int32_t data = Terrain::ExtractData(oldValue);
		int32_t data2 = SetColor(0, GetColor(data));
        dropValues.push_back(BlockDropValue { Terrain::MakeBlockValue(getIndex(), 0, data2), 1 });
    }
    bool StairsBlock::isFaceTransparent(int32_t face, int32_t value)
    {
		int32_t data = Terrain::ExtractData(value);
		bool isUpsideDown = GetIsUpsideDown(data);
		switch (face)
		{
		case 4:
			return !isUpsideDown;
		case 5:
			return isUpsideDown;
		default:
			switch (GetCornerType(data))
			{
			case CornerType::None:
			    {
			    	int32_t rotation2 = GetRotation(data);
			    	return face != ((rotation2 + 2) & 3);
			    }
			case CornerType::OneQuarter:
				return true;
			default:
			    {
			    	int32_t rotation = GetRotation(data);
			    	if (face != ((rotation + 1) & 3))
			    	{
			    		return face != ((rotation + 2) & 3);
			    	}
			    	return false;
			    }
			}
		}
    }
    BlockPlacementData StairsBlock::getPlacementValue(ComponentMiner *componentMiner, int32_t value, const TerrainRaycastResult &raycastResult)
    {
		Vector3 forward = componentMiner->componentCreature->componentCreatureModel->getEyeRotation().toMatrix().getForward();
		float numBuff[4] = {
			Vector3::Dot(forward, FastVector3::UnitZ),
			Vector3::Dot(forward, FastVector3::UnitX),
			Vector3::Dot(forward, FastVector3::DecUnitZ),
			Vector3::Dot(forward, FastVector3::DecUnitX)
		};
		uint32_t targetIndex = MathUtils::MaxIndex<float>(numBuff, 4);
		int32_t rotation = 0;
		switch (targetIndex)
		{
		case 0:
			rotation = 2;
			break;
		case 1:
			rotation = 3;
			break;
		case 2:
			rotation = 0;
			break;
		case 3:
			rotation = 1;
			break;
		}
        bool isUpsideDown = (raycastResult.cellFace.face == 5);
        int32_t data = Terrain::ExtractData(value);
		BlockPlacementData result;
		result.value = Terrain::MakeBlockValue(getIndex(), 0, SetIsUpsideDown(SetRotation(data, rotation), isUpsideDown));
		result.cellFace = raycastResult.cellFace;
		return result;
    }
    const std::vector<BoundingBox> &StairsBlock::getCustomCollisionBoxes(int32_t value)
    {
        int32_t data = Terrain::ExtractData(value);
        return BlockConstans::stairsCollisionBoxes[GetVariant(data)];
    }


    int32_t StairsBlock::getPaintColor(int32_t value)
    {
        return GetColor(Terrain::ExtractData(value));
    }
    int32_t StairsBlock::paint(int32_t value, int32_t color)
    {
        return Terrain::MakeBlockValue(getIndex(), 0, SetColor(Terrain::ExtractData(value), color));
    }
} // namespace PocketSurvival
